home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / russell / gc32.lha / gc_private.h < prev    next >
C/C++ Source or Header  |  1993-07-20  |  38KB  |  1,047 lines

  1. /* 
  2.  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  3.  * Copyright (c) 1991-1993 by Xerox Corporation.  All rights reserved.
  4.  *
  5.  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  6.  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  7.  *
  8.  * Permission is hereby granted to copy this garbage collector for any purpose,
  9.  * provided the above notices are retained on all copies.
  10.  */
  11.  
  12.  
  13. # ifndef GC_PRIVATE_H
  14. # define GC_PRIVATE_H
  15.  
  16. # ifndef GC_H
  17. #   include "gc.h"
  18. # endif
  19.  
  20. typedef GC_word word;
  21. typedef GC_signed_word signed_word;
  22.  
  23. # ifndef CONFIG_H
  24. #   include "config.h"
  25. # endif
  26.  
  27. # ifndef HEADERS_H
  28. #   include "gc_headers.h"
  29. # endif
  30.  
  31. # ifndef bool
  32.     typedef int bool;
  33. # endif
  34. # define TRUE 1
  35. # define FALSE 0
  36.  
  37. typedef char * ptr_t;    /* A generic pointer to which we can add    */
  38.             /* byte displacments.                */
  39.             
  40. #ifdef __STDC__
  41. #   if !(defined( sony_news ) )
  42. #       include <stddef.h>
  43. #   endif
  44.     typedef void * extern_ptr_t;
  45. #   define VOLATILE volatile
  46. #else
  47.     typedef char * extern_ptr_t;
  48. #   define VOLATILE
  49. #endif
  50.  
  51.  
  52.  
  53. # ifndef OS2
  54. #   include <sys/types.h>
  55. # endif
  56.  
  57. /*********************************/
  58. /*                               */
  59. /* Definitions for conservative  */
  60. /* collector                     */
  61. /*                               */
  62. /*********************************/
  63.  
  64. /*********************************/
  65. /*                               */
  66. /* Easily changeable parameters  */
  67. /*                               */
  68. /*********************************/
  69.  
  70. #define STUBBORN_ALLOC    /* Define stubborn allocation primitives    */
  71.  
  72.  
  73. #define ALL_INTERIOR_POINTERS
  74.             /* Forces all pointers into the interior of an     */
  75.             /* object to be considered valid.  Also causes the    */
  76.             /* sizes of all objects to be inflated by at least     */
  77.             /* one byte.  This should suffice to guarantee    */
  78.             /* that in the presence of a compiler that does    */
  79.             /* not perform garbage-collector-unsafe        */
  80.             /* optimizations, all portable, strictly ANSI    */
  81.             /* conforming C programs should be safely usable    */
  82.             /* with malloc replaced by GC_malloc and free    */
  83.             /* calls removed.  There are several disadvantages: */
  84.             /* 1. There are probably no interesting, portable,    */
  85.             /*    strictly ANSI    conforming C programs.        */
  86.             /* 2. This option makes it hard for the collector    */
  87.             /*    to allocate space that is not ``pointed to''  */
  88.             /*    by integers, etc.  Under SunOS 4.X with a     */
  89.             /*    statically linked libc, we empiricaly        */
  90.             /*    observed that it would be difficult to     */
  91.             /*      allocate individual objects larger than 100K.    */
  92.             /*       Even if only smaller objects are allocated,    */
  93.             /*    more swap space is likely to be needed.       */
  94.             /*    Fortunately, much of this will never be    */
  95.             /*    touched.                    */
  96.             /* If you can easily avoid using this option, do.    */
  97.             /* If not, try to keep individual objects small.    */
  98. #undef ALL_INTERIOR_POINTERS
  99.             
  100. #define PRINTSTATS  /* Print garbage collection statistics              */
  101.             /* For less verbose output, undefine in reclaim.c     */
  102.  
  103. #define PRINTTIMES  /* Print the amount of time consumed by each garbage   */
  104.             /* collection.                                         */
  105.  
  106. #define PRINTBLOCKS /* Print object sizes associated with heap blocks,     */
  107.             /* whether the objects are atomic or composite, and    */
  108.             /* whether or not the block was found to be empty      */
  109.             /* duing the reclaim phase.  Typically generates       */
  110.             /* about one screenful per garbage collection.         */
  111. #undef PRINTBLOCKS
  112.  
  113. #define PRINTBLACKLIST     /* Print black listed blocks, i.e. values that     */
  114.             /* cause the allocator to avoid allocating certain */
  115.             /* blocks in order to avoid introducing "false       */
  116.             /* hits".                       */
  117. #undef PRINTBLACKLIST
  118.  
  119. #ifdef SILENT
  120. #  ifdef PRINTSTATS
  121. #    undef PRINTSTATS
  122. #  endif
  123. #  ifdef PRINTTIMES
  124. #    undef PRINTTIMES
  125. #  endif
  126. #  ifdef PRINTNBLOCKS
  127. #    undef PRINTNBLOCKS
  128. #  endif
  129. #endif
  130.  
  131. #if defined(PRINTSTATS) && !defined(GATHERSTATS)
  132. #   define GATHERSTATS
  133. #endif
  134.  
  135.  
  136. #ifdef SPARC
  137. #   define ALIGN_DOUBLE  /* Align objects of size > 1 word on 2 word   */
  138.              /* boundaries.  Wasteful of memory, but       */
  139.              /* apparently required by SPARC architecture. */
  140. #endif
  141.  
  142. #if defined(SPARC) || defined(M68K) && defined(SUNOS)
  143. # if !defined(PCR)
  144. #   define DYNAMIC_LOADING /* Search dynamic libraries for roots.    */
  145. # else
  146.     /* PCR handles any dynamic loading whether with dlopen or otherwise */
  147. # endif
  148. #endif
  149.  
  150. #define MERGE_SIZES /* Round up some object sizes, so that fewer distinct */
  151.             /* free lists are actually maintained.  This applies  */
  152.             /* only to the top level routines in misc.c, not to   */
  153.             /* user generated code that calls GC_allocobj and     */
  154.             /* GC_allocaobj directly.                             */
  155.             /* Slows down average programs slightly.  May however */
  156.             /* substantially reduce fragmentation if allocation   */
  157.             /* request sizes are widely scattered.                */
  158.             /* May save significant amounts of space for obj_map  */
  159.             /* entries.                          */
  160.  
  161. /* ALIGN_DOUBLE requires MERGE_SIZES at present. */
  162. # if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES)
  163. #   define MERGE_SIZES
  164. # endif
  165.  
  166.  
  167. # define HINCR 16          /* Initial heap increment, in blocks of 4K        */
  168. # define MAXHINCR 512      /* Maximum heap increment, in blocks              */
  169. # define HINCR_MULT 5      /* After each new allocation, GC_hincr is           */
  170. # define HINCR_DIV 4       /* multiplied by HINCR_MULT/HINCR_DIV         */
  171. # define GC_MULT 3         /* Don't collect if the fraction of   */
  172.                /* non-collectable memory in the heap */
  173.                /* exceeds GC_MUL/GC_DIV              */
  174. # define GC_DIV  4
  175.  
  176. # define NON_GC_HINCR ((word)8)
  177.                /* Heap increment if most of heap if collection */
  178.                /* was suppressed because most of heap is not   */
  179.                /* collectable                                  */
  180.  
  181. /*********************************/
  182. /*                               */
  183. /* OS interface routines     */
  184. /*                               */
  185. /*********************************/
  186.  
  187. #include <time.h>
  188. #if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4)
  189.    clock_t clock();    /* Not in time.h, where it belongs    */
  190. #endif
  191. #if !defined(CLOCKS_PER_SEC)
  192. #   define CLOCKS_PER_SEC 1000000
  193. /*
  194.  * This is technically a bug in the implementation.  ANSI requires that
  195.  * CLOCKS_PER_SEC be defined.  But at least under SunOS4.1.1, it isn't.
  196.  * Also note that the combination of ANSI C and POSIX is incredibly gross
  197.  * here. The type clock_t is used by both clock() and times().  But on
  198.  * some machines thes use different notions of a clock tick,  CLOCKS_PER_SEC
  199.  * seems to apply only to clock.  Hence we use it here.  On many machines,
  200.  * including SunOS, clock actually uses units of microseconds (which are
  201.  * not really clock ticks).
  202.  */
  203. #endif
  204. #define CLOCK_TYPE clock_t
  205. #define GET_TIME(x) x = clock()
  206. #define MS_TIME_DIFF(a,b) ((unsigned long) \
  207.         (1000.0*(double)((a)-(b))/(double)CLOCKS_PER_SEC))
  208.  
  209. /* We use bzero and bcopy internally.  They may not be available.    */
  210. # if defined(SPARC) && defined(SUNOS4)
  211. #   define BCOPY_EXISTS
  212. # endif
  213. # if defined(M68K) && defined(SUNOS)
  214. #   define BCOPY_EXISTS
  215. # endif
  216. # if defined(VAX)
  217. #   define BCOPY_EXISTS
  218. # endif
  219.  
  220. # ifndef BCOPY_EXISTS
  221. #   include <string.h>
  222. #   define bcopy(x,y,n) memcpy(y,x,n)
  223. #   define bzero(x,n)  memset(x, 0, n)
  224. # endif
  225.  
  226. /* HBLKSIZE aligned allocation.  0 is taken to mean failure     */
  227. /* space is assumed to be cleared.                */
  228. # ifdef PCR
  229.     char * real_malloc();
  230. #   define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + HBLKSIZE) \
  231.                   + HBLKSIZE-1)
  232. #   define THREADS
  233. # else
  234. #   ifdef OS2
  235.       void * os2_alloc(size_t bytes);
  236. #     define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc((size_t)bytes + HBLKSIZE) \
  237.                                     + HBLKSIZE-1)
  238. #   else
  239.       extern ptr_t GC_unix_get_mem();
  240. #     define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)
  241. #   endif
  242. # endif
  243.  
  244. /*
  245.  * Mutual exclusion between allocator/collector routines.
  246.  * Needed if there is more than one allocator thread.
  247.  * FASTLOCK() is assumed to try to acquire the lock in a cheap and
  248.  * dirty way that is acceptable for a few instructions, e.g. by
  249.  * inhibiting preemption.  This is assumed to have succeeded only
  250.  * if a subsequent call to FASTLOCK_SUCCEEDED() returns TRUE.
  251.  * FASTUNLOCK() is called whether or not FASTLOCK_SUCCEEDED().
  252.  * If signals cannot be tolerated with the FASTLOCK held, then
  253.  * FASTLOCK should disable signals.  The code executed under
  254.  * FASTLOCK is otherwise immune to interruption, provided it is
  255.  * not restarted.
  256.  * DCL_LOCK_STATE declares any local variables needed by LOCK and UNLOCK
  257.  * and/or DISABLE_SIGNALS and ENABLE_SIGNALS and/or FASTLOCK.
  258.  * (There is currently no equivalent for FASTLOCK.)
  259.  */  
  260. # ifdef PCR
  261. #    include  "pcr/th/PCR_Th.h"
  262. #    include  "pcr/th/PCR_ThCrSec.h"
  263.      extern struct PCR_Th_MLRep GC_allocate_ml;
  264. #    define DCL_LOCK_STATE  PCR_sigset_t GC_old_sig_mask
  265. #    define LOCK() PCR_Th_ML_Acquire(&GC_allocate_ml) 
  266. #    define UNLOCK() PCR_Th_ML_Release(&GC_allocate_ml)
  267. #    define FASTLOCK() PCR_ThCrSec_EnterSys()
  268.      /* Here we cheat (a lot): */
  269. #        define FASTLOCK_SUCCEEDED() (*(int *)(&GC_allocate_ml) == 0)
  270.         /* TRUE if nobody currently holds the lock */
  271. #    define FASTUNLOCK() PCR_ThCrSec_ExitSys()
  272. # else
  273. #    define DCL_LOCK_STATE
  274. #    define LOCK()
  275. #    define UNLOCK()
  276. #    define FASTLOCK() LOCK()
  277. #    define FASTLOCK_SUCCEEDED() TRUE
  278. #    define FASTUNLOCK() UNLOCK()
  279. # endif
  280.  
  281. /* Delay any interrupts or signals that may abort this thread.  Data    */
  282. /* structures are in a consistent state outside this pair of calls.    */
  283. /* ANSI C allows both to be empty (though the standard isn't very    */
  284. /* clear on that point).  Standard malloc implementations are usually    */
  285. /* neither interruptable nor thread-safe, and thus correspond to    */
  286. /* empty definitions.                            */
  287. # ifdef PCR
  288. #   define DISABLE_SIGNALS() \
  289.          PCR_Th_SetSigMask(PCR_allSigsBlocked,&GC_old_sig_mask)
  290. #   define ENABLE_SIGNALS() \
  291.         PCR_Th_SetSigMask(&GC_old_sig_mask, NIL)
  292. # else
  293. #   if 0    /* Useful for debugging, and unusually        */
  294.          /* correct client code.                */
  295. #     define DISABLE_SIGNALS()
  296. #     define ENABLE_SIGNALS()
  297. #   else
  298. #     define DISABLE_SIGNALS() GC_disable_signals()
  299.     void GC_disable_signals();
  300. #     define ENABLE_SIGNALS() GC_enable_signals()
  301.     void GC_enable_signals();
  302. #   endif
  303. # endif
  304.  
  305. /*
  306.  * Stop and restart mutator threads.
  307.  */
  308. # ifdef PCR
  309. #     include "pcr/th/PCR_ThCtl.h"
  310. #     define STOP_WORLD() \
  311.      PCR_ThCtl_SetExclusiveMode(PCR_ThCtl_ExclusiveMode_stopNormal, \
  312.                     PCR_allSigsBlocked, \
  313.                     PCR_waitForever)
  314. #     define START_WORLD() \
  315.     PCR_ThCtl_SetExclusiveMode(PCR_ThCtl_ExclusiveMode_null, \
  316.                     PCR_allSigsBlocked, \
  317.                     PCR_waitForever);
  318. # else
  319. #     define STOP_WORLD()
  320. #     define START_WORLD()
  321. # endif
  322.  
  323. /* Abandon ship */
  324. # ifdef PCR
  325.     void PCR_Base_Panic(const char *fmt, ...);
  326. #   define ABORT(s) PCR_Base_Panic(s)
  327. # else
  328. #   define ABORT(s) abort(s)
  329. # endif
  330.  
  331. /* Exit abnormally, but without making a mess (e.g. out of memory) */
  332. # ifdef PCR
  333.     void PCR_Base_Exit(int status);
  334. #   define EXIT() PCR_Base_Exit(1)
  335. # else
  336. #   define EXIT() (void)exit(1)
  337. # endif
  338.  
  339. /* Print warning message, e.g. almost out of memory.    */
  340. # define WARN(s) GC_printf0(s)
  341.  
  342. /*********************************/
  343. /*                               */
  344. /* Word-size-dependent defines   */
  345. /*                               */
  346. /*********************************/
  347.  
  348. #if CPP_WORDSZ == 32
  349. #  define WORDS_TO_BYTES(x)   ((x)<<2)
  350. #  define BYTES_TO_WORDS(x)   ((x)>>2)
  351. #  define LOGWL               ((word)5)    /* log[2] of CPP_WORDSZ */
  352. #  define modWORDSZ(n) ((n) & 0x1f)          /* n mod size of word        */
  353. #endif
  354.  
  355. #if CPP_WORDSZ == 64
  356. #  define WORDS_TO_BYTES(x)   ((x)<<3)
  357. #  define BYTES_TO_WORDS(x)   ((x)>>3)
  358. #  define LOGWL               ((word)6)    /* log[2] of CPP_WORDSZ */
  359. #  define modWORDSZ(n) ((n) & 0x3f)          /* n mod size of word        */
  360. #endif
  361.  
  362. #define WORDSZ ((word)CPP_WORDSZ)
  363. #define SIGNB  ((word)1 << (WORDSZ-1))
  364. #define BYTES_PER_WORD      ((word)(sizeof (word)))
  365. #define ONES                ((word)(-1))
  366. #define divWORDSZ(n) ((n) >> LOGWL)       /* divide n by size of word      */
  367.  
  368. /*********************/
  369. /*                   */
  370. /*  Size Parameters  */
  371. /*                   */
  372. /*********************/
  373.  
  374. /*  heap block size, bytes. Should be power of 2 */
  375.  
  376. #if CPP_WORDSZ == 32
  377. #   define CPP_LOG_HBLKSIZE 12
  378. #else
  379. #   define CPP_LOG_HBLKSIZE 13
  380. #endif
  381. #define LOG_HBLKSIZE   ((word)CPP_LOG_HBLKSIZE)
  382. #define CPP_HBLKSIZE (1 << CPP_LOG_HBLKSIZE)
  383. #define HBLKSIZE ((word)CPP_HBLKSIZE)
  384.  
  385.  
  386. /*  max size objects supported by freelist (larger objects may be   */
  387. /*  allocated, but less efficiently)                                */
  388.  
  389. #define CPP_MAXOBJSZ    BYTES_TO_WORDS(CPP_HBLKSIZE/2)
  390. #define MAXOBJSZ ((word)CPP_MAXOBJSZ)
  391.         
  392. # define divHBLKSZ(n) ((n) >> LOG_HBLKSIZE)
  393.  
  394. # define HBLK_PTR_DIFF(p,q) divHBLKSZ((ptr_t)p - (ptr_t)q)
  395.     /* Equivalent to subtracting 2 hblk pointers.    */
  396.     /* We do it this way because a compiler should    */
  397.     /* find it hard to use an integer division    */
  398.     /* instead of a shift.  The bundled SunOS 4.1    */
  399.     /* o.w. sometimes pessimizes the subtraction to    */
  400.     /* involve a call to .div.            */
  401.  
  402. # define modHBLKSZ(n) ((n) & (HBLKSIZE-1))
  403.  
  404. # define HBLKPTR(objptr) ((struct hblk *)(((word) (objptr)) & ~(HBLKSIZE-1)))
  405.  
  406. # define HBLKDISPL(objptr) (((word) (objptr)) & (HBLKSIZE-1))
  407.  
  408. /* Round up byte allocation requests to integral number of words: */
  409. # ifdef ALL_INTERIOR_POINTERS
  410. #   define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1))
  411. # else
  412. #   define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
  413. # endif
  414.  
  415.  
  416. /*
  417.  * Hash table representation of sets of pages.  This assumes it is
  418.  * OK to add spurious entries to sets.
  419.  * Used by black-listing code, and perhaps by dirty bit maintenance code.
  420.  */
  421.  
  422. # define LOG_PHT_ENTRIES  14    /* Collisions are likely if heap grows    */
  423.                 /* to more than 16K hblks = 64MB.    */
  424.                 /* Each hash table occupies 2K bytes.   */
  425. # define PHT_ENTRIES ((word)1 << LOG_PHT_ENTRIES)
  426. # define PHT_SIZE (PHT_ENTRIES >> LOGWL)
  427. typedef word page_hash_table[PHT_SIZE];
  428.  
  429. # define PHT_HASH(addr) ((((word)(addr)) >> LOG_HBLKSIZE) & (PHT_ENTRIES - 1))
  430.  
  431. # define get_pht_entry_from_index(bl, index) \
  432.         (((bl)[divWORDSZ(index)] >> modWORDSZ(index)) & 1)
  433. # define set_pht_entry_from_index(bl, index) \
  434.         (bl)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index)
  435. # define clear_pht_entry_from_index(bl, index) \
  436.         (bl)[divWORDSZ(index)] &= ~((word)1 << modWORDSZ(index))
  437.     
  438.  
  439.  
  440. /********************************************/
  441. /*                                          */
  442. /*    H e a p   B l o c k s                 */
  443. /*                                          */
  444. /********************************************/
  445.  
  446. /*  heap block header */
  447. #define HBLKMASK   (HBLKSIZE-1)
  448.  
  449. #define BITS_PER_HBLK (HBLKSIZE * 8)
  450.  
  451. #define MARK_BITS_PER_HBLK (BITS_PER_HBLK/CPP_WORDSZ)
  452.        /* upper bound                                    */
  453.        /* We allocate 1 bit/word.  Only the first word   */
  454.        /* in each object is actually marked.             */
  455.  
  456. # ifdef ALIGN_DOUBLE
  457. #   define MARK_BITS_SZ (((MARK_BITS_PER_HBLK + 2*CPP_WORDSZ - 1) \
  458.               / (2*CPP_WORDSZ))*2)
  459. # else
  460. #   define MARK_BITS_SZ ((MARK_BITS_PER_HBLK + CPP_WORDSZ - 1)/CPP_WORDSZ)
  461. # endif
  462.        /* Upper bound on number of mark words per heap block  */
  463.        
  464. /* Mark stack entries. */
  465. typedef struct ms_entry {
  466.     word * mse_start;  /* inclusive */
  467.     word * mse_end;    /* exclusive */
  468. } mse;
  469.  
  470. typedef mse * (*mark_proc)(/* word * addr, hdr * hhdr, mse * msp, mse * msl */);
  471.       /* Procedure to arrange for the descendents of the object at    */
  472.       /* addr to be marked.  Msp points at the top entry on the    */
  473.       /* mark stack.  Msl delimits the hot end of the mark stack.    */
  474.       /* hhdr is the hdr structure corresponding to addr.        */
  475.       /* Returns the new mark stack pointer.            */
  476.  
  477. struct hblkhdr {
  478.     word hb_sz;  /* If in use, size in words, of objects in the block. */
  479.          /* if free, the size in bytes of the whole block      */
  480.     struct hblk * hb_next;     /* Link field for hblk free list     */
  481.                     /* and for lists of chunks waiting to be */
  482.                     /* reclaimed.                 */
  483.     mark_proc hb_mark_proc;   /* Procedure to mark objects.  Can     */
  484.                     /* also be retrived through obj_kind.     */
  485.                     /* But one level of indirection matters  */
  486.                     /* here.                 */
  487.     char* hb_map;    /* A pointer to a pointer validity map of the block. */
  488.                       /* See GC_obj_map.                     */
  489.                      /* Valid for all blocks with headers.             */
  490.                      /* Free blocks point to GC_invalid_map.             */
  491.     unsigned short hb_obj_kind;
  492.                  /* Kind of objects in the block.  Each kind     */
  493.                  /* identifies a mark procedure and a set of     */
  494.                  /* list headers.  sometimes called regions.    */
  495.     unsigned short hb_last_reclaimed;
  496.                     /* Value of GC_gc_no when block was    */
  497.                     /* last allocated or swept. May wrap.   */
  498.     word hb_marks[MARK_BITS_SZ];
  499.                 /* Bit i in the array refers to the             */
  500.                 /* object starting at the ith word (header      */
  501.                 /* INCLUDED) in the heap block.                 */
  502.                 /* The lsb of word 0 is numbered 0.            */
  503. };
  504.  
  505. /*  heap block body */
  506.  
  507. # define DISCARD_WORDS 0
  508.     /* Number of words to be dropped at the beginning of each block    */
  509.     /* Must be a multiple of WORDSZ.  May reasonably be nonzero    */
  510.     /* on machines that don't guarantee longword alignment of    */
  511.     /* pointers, so that the number of false hits is minimized.    */
  512.     /* 0 and WORDSZ are probably the only reasonable values.    */
  513.  
  514. # define BODY_SZ ((HBLKSIZE-WORDS_TO_BYTES(DISCARD_WORDS))/sizeof(word))
  515.  
  516. struct hblk {
  517. #   if (DISCARD_WORDS != 0)
  518.         word garbage[DISCARD_WORDS];
  519. #   endif
  520.     word hb_body[BODY_SZ];
  521. };
  522.  
  523. # define HDR_WORDS ((word)DISCARD_WORDS)
  524. # define HDR_BYTES ((word)WORDS_TO_BYTES(DISCARD_WORDS))
  525.  
  526. # define OBJ_SZ_TO_BLOCKS(sz) \
  527.     divHBLKSZ(HDR_BYTES + WORDS_TO_BYTES(sz) + HBLKSIZE-1)
  528.     /* Size of block (in units of HBLKSIZE) needed to hold objects of    */
  529.     /* given sz (in words).                        */
  530.  
  531. /* Object free list link */
  532. # define obj_link(p) (*(ptr_t *)(p))
  533.  
  534. /*  lists of all heap blocks and free lists    */
  535. /* These are grouped together in a struct    */
  536. /* so that they can be easily skipped by the    */
  537. /* GC_mark routine.                */
  538. /* The ordering is weird to make GC_malloc    */
  539. /* faster by keeping the important fields    */
  540. /* sufficiently close together that a        */
  541. /* single load of a base register will do.    */
  542. /* Scalars that could easily appear to        */
  543. /* be pointers are also put here.        */
  544.  
  545. struct _GC_arrays {
  546.   word _heapsize;
  547.   ptr_t _last_heap_addr;
  548.   ptr_t _prev_heap_addr;
  549.   word _words_allocd_before_gc;
  550.         /* Number of words allocated before this    */
  551.         /* collection cycle.                */
  552. # ifdef GATHERSTATS
  553.     word _composite_in_use;
  554.            /* Number of words in accessible composite    */
  555.         /* objects.                    */
  556.     word _atomic_in_use;
  557.            /* Number of words in accessible atomic        */
  558.         /* objects.                    */
  559. # endif
  560.   word _words_allocd;
  561.       /* Number of words allocated during this collection cycle */
  562.   word _words_wasted;
  563.       /* Number of words wasted due to internal fragmentation     */
  564.       /* in large objects allocated since last gc. Approximate.*/
  565.   word _non_gc_bytes_at_gc;
  566.       /* Number of explicitly managed bytes of storage     */
  567.       /* at last collection.                    */
  568.   word _mem_freed;
  569.       /* Number of explicitly deallocated words of memory    */
  570.       /* since last collection.                */
  571.       
  572.   ptr_t _objfreelist[MAXOBJSZ+1];
  573.               /* free list for objects */
  574. # ifdef MERGE_SIZES
  575.     unsigned _size_map[WORDS_TO_BYTES(MAXOBJSZ+1)];
  576.         /* Number of words to allocate for a given allocation request in */
  577.         /* bytes.                             */
  578. # endif 
  579.   ptr_t _aobjfreelist[MAXOBJSZ+1];
  580.               /* free list for atomic objs     */
  581.  
  582.   ptr_t _uobjfreelist[MAXOBJSZ+1];
  583.               /* uncollectable but traced objs     */
  584.  
  585. # ifdef STUBBORN_ALLOC
  586.     ptr_t _sobjfreelist[MAXOBJSZ+1];
  587. # endif
  588.                 /* free list for immutable objects    */
  589.   ptr_t _obj_map[MAXOBJSZ+1];
  590.                        /* If not NIL, then a pointer to a map of valid  */
  591.                    /* object addresses. hbh_map[sz][i] is j if the  */
  592.                    /* address block_start+i is a valid pointer      */
  593.                    /* to an object at                */
  594.                    /* block_start+i&~3 - WORDS_TO_BYTES(j).        */
  595.                    /* (If ALL_INTERIOR_POINTERS is defined, then    */
  596.                    /* instead ((short *)(hbh_map[sz])[i] is j if    */
  597.                    /* block_start+WORDS_TO_BYTES(i) is in the    */
  598.                    /* interior of an object starting at        */
  599.                    /* block_start+WORDS_TO_BYTES(i-j)).        */
  600.                    /* It is OBJ_INVALID if                */
  601.                    /* block_start+WORDS_TO_BYTES(i) is not        */
  602.                    /* valid as a pointer to an object.              */
  603.                    /* We assume that all values of j <= OBJ_INVALID */
  604.                    /* The zeroth entry corresponds to large objects.*/
  605. #   ifdef ALL_INTERIOR_POINTERS
  606. #    define map_entry_type short
  607. #       define OBJ_INVALID 0x7fff
  608. #    define MAP_ENTRY(map, bytes) \
  609.         (((map_entry_type *)(map))[BYTES_TO_WORDS(bytes)])
  610. #    define MAP_ENTRIES BYTES_TO_WORDS(HBLKSIZE)
  611. #    define MAP_SIZE (MAP_ENTRIES * sizeof(map_entry_type))
  612. #    define OFFSET_VALID(displ) TRUE
  613. #    define CPP_MAX_OFFSET (HBLKSIZE - HDR_BYTES - 1)
  614. #    define MAX_OFFSET ((word)CPP_MAX_OFFSET)
  615. #   else
  616. #    define map_entry_type char
  617. #       define OBJ_INVALID 0x7f
  618. #    define MAP_ENTRY(map, bytes) \
  619.         (map)[bytes]
  620. #    define MAP_ENTRIES HBLKSIZE
  621. #    define MAP_SIZE MAP_ENTRIES
  622. #    define CPP_MAX_OFFSET (WORDS_TO_BYTES(OBJ_INVALID) - 1)    
  623. #    define MAX_OFFSET ((word)CPP_MAX_OFFSET)
  624. #     define VALID_OFFSET_SZ \
  625.       (CPP_MAX_OFFSET > WORDS_TO_BYTES(CPP_MAXOBJSZ)? \
  626.        CPP_MAX_OFFSET+1 \
  627.        : WORDS_TO_BYTES(CPP_MAXOBJSZ)+1)
  628.       char _valid_offsets[VALID_OFFSET_SZ];
  629.                 /* GC_valid_offsets[i] == TRUE ==> i     */
  630.                 /* is registered as a displacement.    */
  631. #    define OFFSET_VALID(displ) GC_valid_offsets[displ]
  632.       char _modws_valid_offsets[sizeof(word)];
  633.                 /* GC_valid_offsets[i] ==>          */
  634.                 /* GC_modws_valid_offsets[i%sizeof(word)] */
  635. #   endif
  636.   struct hblk * _reclaim_list[MAXOBJSZ+1];
  637.   struct hblk * _areclaim_list[MAXOBJSZ+1];
  638.   struct hblk * _ureclaim_list[MAXOBJSZ+1];
  639. # ifdef STUBBORN_ALLOC
  640.       struct hblk * _sreclaim_list[MAXOBJSZ+1];
  641.       page_hash_table _changed_pages;
  642.         /* Stubborn object pages that were changes since last call to    */
  643.     /* GC_read_changed.                        */
  644.       page_hash_table _prev_changed_pages;
  645.         /* Stubborn object pages that were changes before last call to    */
  646.     /* GC_read_changed.                        */
  647. # endif
  648. # if defined(PROC_VDB) || defined(MPROTECT_VDB)
  649.       page_hash_table _grungy_pages; /* Pages that were dirty at last        */
  650.                      /* GC_read_dirty.               */
  651. # endif
  652. # define MAX_HEAP_SECTS 256    /* Separately added heap sections. */
  653.   struct HeapSect {
  654.       ptr_t hs_start; word hs_bytes;
  655.   } _heap_sects[MAX_HEAP_SECTS];
  656.   /* Block header index; see gc_headers.h */
  657.   bottom_index _all_nils;
  658.   bottom_index * _top_index [TOP_SZ];
  659. };
  660.  
  661. extern struct _GC_arrays GC_arrays; 
  662.  
  663. # define GC_objfreelist GC_arrays._objfreelist
  664. # define GC_aobjfreelist GC_arrays._aobjfreelist
  665. # define GC_uobjfreelist GC_arrays._uobjfreelist
  666. # define GC_sobjfreelist GC_arrays._sobjfreelist
  667. # define GC_valid_offsets GC_arrays._valid_offsets
  668. # define GC_modws_valid_offsets GC_arrays._modws_valid_offsets
  669. # define GC_reclaim_list GC_arrays._reclaim_list
  670. # define GC_areclaim_list GC_arrays._areclaim_list
  671. # define GC_ureclaim_list GC_arrays._ureclaim_list
  672. # ifdef STUBBORN_ALLOC
  673. #    define GC_sreclaim_list GC_arrays._sreclaim_list
  674. #    define GC_changed_pages GC_arrays._changed_pages
  675. #    define GC_prev_changed_pages GC_arrays._prev_changed_pages
  676. # endif
  677. # define GC_obj_map GC_arrays._obj_map
  678. # define GC_last_heap_addr GC_arrays._last_heap_addr
  679. # define GC_prev_heap_addr GC_arrays._prev_heap_addr
  680. # define GC_words_allocd GC_arrays._words_allocd
  681. # define GC_words_wasted GC_arrays._words_wasted
  682. # define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc
  683. # define GC_mem_freed GC_arrays._mem_freed
  684. # define GC_heapsize GC_arrays._heapsize
  685. # define GC_words_allocd_before_gc GC_arrays._words_allocd_before_gc
  686. # define GC_heap_sects GC_arrays._heap_sects
  687. # define GC_all_nils GC_arrays._all_nils
  688. # define GC_top_index GC_arrays._top_index
  689. # if defined(PROC_VDB) || defined(MPROTECT_VDB)
  690. #   define GC_grungy_pages GC_arrays._grungy_pages
  691. # endif
  692. # ifdef GATHERSTATS
  693. #   define GC_composite_in_use GC_arrays._composite_in_use
  694. #   define GC_atomic_in_use GC_arrays._atomic_in_use
  695. # endif
  696. # ifdef MERGE_SIZES
  697. #   define GC_size_map GC_arrays._size_map
  698. # endif
  699.  
  700. # define beginGC_arrays ((ptr_t)(&GC_arrays))
  701. # define endGC_arrays (((ptr_t)(&GC_arrays)) + (sizeof GC_arrays))
  702.  
  703.  
  704. # define MAXOBJKINDS 16
  705.  
  706. /* Object kinds: */
  707. extern struct obj_kind {
  708.    ptr_t *ok_freelist;    /* Array of free listheaders for this kind of object */
  709.                /* Point either to GC_arrays or to storage allocated */
  710.                /* with GC_scratch_alloc.                 */
  711.    struct hblk **ok_reclaim_list;
  712.                /* List headers for lists of blocks waiting to be */
  713.                /* swept.                      */
  714.    mark_proc ok_mark_proc; /* Procedure to either mark referenced objects,  */
  715.                   /* or push them on the mark stack.            */
  716.    bool ok_init;     /* Clear objects before putting them on the free list. */
  717. } GC_obj_kinds[MAXOBJKINDS];
  718. /* Predefined kinds: */
  719. # define PTRFREE 0
  720. # define NORMAL  1
  721. # define UNCOLLECTABLE 2
  722. # define STUBBORN 3
  723.  
  724. extern word GC_n_heap_sects;    /* Number of separately added heap    */
  725.                 /* sections.                */
  726.  
  727. extern int GC_n_kinds;
  728.  
  729. extern char * GC_invalid_map;
  730.             /* Pointer to the nowhere valid hblk map */
  731.             /* Blocks pointing to this map are free. */
  732.  
  733. extern struct hblk * GC_hblkfreelist;
  734.                 /* List of completely empty heap blocks    */
  735.                 /* Linked through hb_next field of     */
  736.                 /* header structure associated with    */
  737.                 /* block.                */
  738.  
  739. extern bool GC_is_initialized;        /* GC_init() has been run.    */
  740.  
  741. extern bool GC_objects_are_marked;    /* There are marked objects in  */
  742.                     /* the heap.            */
  743.  
  744. # ifndef PCR
  745.     extern ptr_t GC_stackbottom;    /* Cool end of user stack    */
  746. # endif
  747.  
  748. extern word GC_hincr;          /* current heap increment, in blocks    */
  749.  
  750. extern word GC_root_size;    /* Total size of registered root sections */
  751.  
  752. extern bool GC_debugging_started;    /* GC_debug_malloc has been called. */ 
  753.  
  754. extern ptr_t GC_least_plausible_heap_addr;
  755. extern ptr_t GC_greatest_plausible_heap_addr;
  756.             /* Bounds on the heap.  Guaranteed valid    */
  757.             /* Likely to include future heap expansion.    */
  758.             
  759. /* Operations */
  760. # define update_GC_hincr  GC_hincr = (GC_hincr * HINCR_MULT)/HINCR_DIV; \
  761.                if (GC_hincr > MAXHINCR) {GC_hincr = MAXHINCR;}
  762. # ifndef abs
  763. #   define abs(x)  ((x) < 0? (-(x)) : (x))
  764. # endif
  765.  
  766.  
  767. /*  Marks are in a reserved area in                          */
  768. /*  each heap block.  Each word has one mark bit associated  */
  769. /*  with it. Only those corresponding to the beginning of an */
  770. /*  object are used.                                         */
  771.  
  772.  
  773. /* Mark bit perations */
  774.  
  775. /*
  776.  * Retrieve, set, clear the mark bit corresponding
  777.  * to the nth word in a given heap block.
  778.  *
  779.  * (Recall that bit n corresponds to object beginning at word n
  780.  * relative to the beginning of the block, including unused words)
  781.  */
  782.  
  783. # define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \
  784.                 >> (modWORDSZ(n))) & (word)1)
  785. # define set_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \
  786.                 |= (word)1 << modWORDSZ(n)
  787.  
  788. # define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \
  789.                 &= ~((word)1 << modWORDSZ(n))
  790.  
  791. /* Important internal collector routines */
  792.  
  793. void GC_apply_to_all_blocks(/*fn, client_data*/);
  794.             /* Invoke fn(hbp, client_data) for each     */
  795.             /* allocated heap block.            */
  796. struct hblk * GC_next_block(/* struct hblk * h */);
  797. mse * GC_no_mark_proc(/*addr,hhdr,msp,msl*/);
  798.             /* Mark procedure for PTRFREE objects.    */
  799. mse * GC_normal_mark_proc(/*addr,hhdr,msp,msl*/);
  800.             /* Mark procedure for NORMAL objects.    */
  801. void GC_mark_init();
  802. void GC_clear_marks();    /* Clear mark bits for all heap objects. */
  803. void GC_mark_from_mark_stack(); /* Mark from everything on the mark stack. */
  804.                 /* Return after about one pages worth of   */
  805.                 /* work.                   */
  806. bool GC_mark_stack_empty();
  807. bool GC_mark_some();    /* Perform about one pages worth of marking    */
  808.             /* work of whatever kind is needed.  Returns    */
  809.             /* quickly if no collection is in progress.    */
  810.             /* Return TRUE if mark phase finished.        */
  811. void GC_initiate_full();    /* initiate full collection.        */
  812. void GC_initiate_partial();    /* initiate partial collection.        */            
  813. void GC_push_all(/*b,t*/);    /* Push everything in a range         */
  814.                 /* onto mark stack.            */
  815. void GC_push_dirty(/*b,t*/);      /* Push all possibly changed         */
  816.                   /* subintervals of [b,t) onto        */
  817.                   /* mark stack.            */
  818. void GC_push_conditional(/* ptr_t b, ptr_t t, bool all*/);
  819.                                 /* Do either of the above, depending    */
  820.                 /* on the third arg.            */
  821. void GC_push_all_stack(/*b,t*/);    /* As above, but consider        */
  822.                     /*  interior pointers as valid      */
  823. void GC_remark();    /* Mark from all marked objects.  Used    */
  824.              /* only if we had to drop something.    */
  825. void GC_push_one(/*p*/);    /* If p points to an object, mark it    */
  826.                 /* and push contents on the mark stack    */
  827. void GC_push_one_checked(/*p*/); /* Ditto, omits plausibility test    */
  828. void GC_push_marked(/* struct hblk h, hdr * hhdr */);
  829.         /* Push contents of all marked objects in h onto    */
  830.         /* mark stack.                        */
  831. struct hblk * GC_push_next_marked_dirty(/* h */);
  832.         /* Invoke GC_push_marked on next dirty block above h.    */
  833.         /* Return a pointer just past the end of this block.    */
  834. struct hblk * GC_push_next_marked(/* h */);
  835.         /* Ditto, but also mark from clean pages.    */
  836. struct hblk * GC_push_next_marked_uncollectable(/* h */);
  837.         /* Ditto, but mark only from uncollectable pages.    */
  838. void GC_stopped_mark(); /* Mark from all roots and rescuers    */
  839.             /* with the world stopped.        */
  840. void GC_clear_hdr_marks(/* hhdr */);  /* Clear the mark bits in a header */
  841. void GC_add_roots_inner();
  842. void GC_register_dynamic_libraries();
  843.         /* Add dynamic library data sections to the root set. */
  844.  
  845. /* Machine dependent startup routines */
  846. ptr_t GC_get_stack_base();
  847. void GC_register_data_segments();
  848.              
  849. # ifndef ALL_INTERIOR_POINTERS
  850.     void GC_add_to_black_list_normal(/* bits */);
  851.             /* Register bits as a possible future false    */
  852.             /* reference from the heap or static data    */
  853. #   define GC_ADD_TO_BLACK_LIST_NORMAL(bits) GC_add_to_black_list_normal(bits)
  854. # else
  855. #   define GC_ADD_TO_BLACK_LIST_NORMAL(bits) GC_add_to_black_list_stack(bits)
  856. # endif
  857.  
  858. void GC_add_to_black_list_stack(/* bits */);
  859. struct hblk * GC_is_black_listed(/* h, len */);
  860.             /* If there are likely to be false references    */
  861.             /* to a block starting at h of the indicated    */
  862.             /* length, then return the next plausible    */
  863.             /* starting location for h that might avoid    */
  864.             /* these false references.            */
  865. void GC_promote_black_lists();
  866.             /* Declare an end to a black listing phase.    */
  867.              
  868. ptr_t GC_scratch_alloc(/*bytes*/);
  869.                 /* GC internal memory allocation for    */
  870.                 /* small objects.  Deallocation is not  */
  871.                 /* possible.                */
  872.                 
  873. void GC_invalidate_map(/* hdr */);
  874.                 /* Remove the object map associated    */
  875.                 /* with the block.  This identifies    */
  876.                 /* the block as invalid to the mark    */
  877.                 /* routines.                */
  878. bool GC_add_map_entry(/*sz*/);
  879.                 /* Add a heap block map for objects of    */
  880.                 /* size sz to obj_map.            */
  881.                 /* Return FALSE on failure.        */
  882. void GC_register_displacement_inner(/*offset*/);
  883.                 /* Version of GC_register_displacement    */
  884.                 /* that assumes lock is already held    */
  885.                 /* and signals are already disabled.    */
  886.                 
  887. void GC_init_inner();
  888.                 
  889. void GC_new_hblk(/*size_in_words, kind*/);
  890.                 /* Allocate a new heap block, and build */
  891.                 /* a free list in it.            */                
  892. struct hblk * GC_allochblk(/*size_in_words, kind*/);
  893.                 /* Allocate a heap block, clear it if    */
  894.                 /* for composite objects, inform    */
  895.                 /* the marker that block is valid    */
  896.                 /* for objects of indicated size.    */
  897.                 /* sz < 0 ==> atomic.            */ 
  898. void GC_freehblk();        /* Deallocate a heap block and mark it  */
  899.                 /* as invalid.                */
  900.                 
  901. void GC_start_reclaim(/*abort_if_found*/);
  902.                 /* Restore unmarked objects to free    */
  903.                 /* lists, or (if abort_if_found is    */
  904.                 /* TRUE) report them.            */
  905.                 /* Sweeping of small object pages is    */
  906.                 /* largely deferred.            */
  907. void GC_continue_reclaim(/*size, kind*/);
  908.                 /* Sweep pages of the given size and    */
  909.                 /* kind, as long as possible, and    */
  910.                 /* as long as the corr. free list is    */
  911.                 /* empty.                */
  912. void GC_reclaim_or_delete_all();
  913.                 /* Arrange for all reclaim lists to be    */
  914.                 /* empty.  Judiciously choose between    */
  915.                 /* sweeping and discarding each page.    */
  916. bool GC_gcollect_inner();
  917.                 /* Collect; caller must have acquired    */
  918.                 /* lock and disabled signals.        */
  919.                 /* FALSE return indicates nothing was    */
  920.                 /* done due to insufficient allocation. */
  921. void GC_finish_collection();    /* Finish collection.  Mark bits are    */
  922.                 /* consistent and lock is still held.    */
  923. bool GC_collect_or_expand(/* needed_blocks */);
  924.                 /* Collect or expand heap in an attempt */
  925.                 /* make the indicated number of free    */
  926.                 /* blocks available.  Should be called    */
  927.                 /* until it fails by returning FALSE.    */
  928. void GC_init();            /* Initialize collector.        */
  929. void GC_collect_a_little(/* n */);
  930.                 /* Do n units worth of garbage         */
  931.                 /* collection work, if appropriate.    */
  932.                 /* A unit is an amount appropriate for  */
  933.                 /* HBLKSIZE bytes of allocation.    */
  934. ptr_t GC_generic_malloc(/* bytes, kind */);
  935.                 /* Allocate an object of the given    */
  936.                 /* kind.  By default, there are only    */
  937.                 /* two kinds: composite, and atomic.    */
  938.                 /* We claim it's possible for clever    */
  939.                 /* client code that understands GC    */
  940.                 /* internals to add more, e.g. to    */
  941.                 /* communicate object layout info    */
  942.                 /* to the collector.            */
  943. ptr_t GC_generic_malloc_inner(/* bytes, kind */);
  944.                 /* Ditto, but I already hold lock, etc.    */
  945. ptr_t GC_generic_malloc_words_small(/*words, kind*/);
  946.                 /* As above, but size in units of words */
  947.                 /* Bypasses MERGE_SIZES.  Assumes    */
  948.                 /* words <= MAXOBJSZ.            */
  949. ptr_t GC_allocobj(/* sz_inn_words, kind */);
  950.                 /* Make the indicated               */
  951.                 /* free list nonempty, and return its    */
  952.                 /* head.                */
  953.                 
  954. bool GC_install_header(/*h*/);
  955.                 /* Install a header for block h.    */
  956.                 /* Return FALSE on failure.        */
  957. bool GC_install_counts(/*h, sz*/);
  958.                 /* Set up forwarding counts for block    */
  959.                 /* h of size sz.            */
  960.                 /* Return FALSE on failure.        */
  961. void GC_remove_header(/*h*/);
  962.                 /* Remove the header for block h.    */
  963. void GC_remove_counts(/*h, sz*/);
  964.                 /* Remove forwarding counts for h.    */
  965. hdr * GC_find_header(/*p*/);    /* Debugging only.            */
  966.  
  967. void GC_finalize();    /* Perform all indicated finalization actions    */
  968.             /* on unmarked objects.                */
  969.             
  970. void GC_add_to_heap(/*p, bytes*/);
  971.             /* Add a HBLKSIZE aligned chunk to the heap.    */
  972.  
  973. void GC_print_obj(/* ptr_t p */);
  974.             /* P points to somewhere inside an object with    */
  975.             /* debugging info.  Print a human readable    */
  976.             /* description of the object to stderr.        */
  977. extern void (*GC_check_heap)();
  978.             /* Check that all objects in the heap with     */
  979.             /* debugging info are intact.  Print         */
  980.             /* descriptions of any that are not.        */
  981.             
  982. /* Virtual dirty bit implementation:        */
  983. /* Each implementation exports the following:    */
  984. void GC_read_dirty();    /* Retrueve dirty bits.    */
  985. bool GC_page_was_dirty(/* struct hblk * h  */);
  986.             /* Read retrieved dirty bits.    */
  987. void GC_write_hint(/* struct hblk * h  */);
  988.             /* h is about to be written.    */
  989. void GC_dirty_init();
  990.  
  991. /* Slow/general mark bit manipulation: */
  992. bool GC_is_marked();
  993. void GC_clear_mark_bit();
  994. void GC_set_mark_bit();
  995.  
  996. /* Stubborn objects: */
  997. void GC_read_changed();    /* Analogous to GC_read_dirty */
  998. bool GC_page_was_changed(/* h */);    /* Analogous to GC_page_was_dirty */
  999. void GC_clean_changing_list();    /* Collect obsolete changing list entries */
  1000. void GC_stubborn_init();
  1001.  
  1002. /* Debugging print routines: */
  1003. void GC_print_block_list();
  1004. void GC_print_hblkfreelist();
  1005.  
  1006. /* Logging and diagnostic output:     */
  1007. void GC_printf(/* format, a, b, c, d, e, f */);
  1008.             /* A version of printf that doesn't allocate,    */
  1009.             /* is restricted to long arguments, and        */
  1010.             /* (unfortunately) doesn't use varargs for    */
  1011.             /* portability.  Restricted to 6 args and    */
  1012.             /* 1K total output length.            */
  1013.             /* (We use sprintf.  Hopefully that doesn't    */
  1014.             /* allocate for long arguments.)          */
  1015. # define GC_printf0(f) GC_printf(f, 0l, 0l, 0l, 0l, 0l, 0l)
  1016. # define GC_printf1(f,a) GC_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l)
  1017. # define GC_printf2(f,a,b) GC_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l)
  1018. # define GC_printf3(f,a,b,c) GC_printf(f, (long)a, (long)b, (long)c, 0l, 0l, 0l)
  1019. # define GC_printf4(f,a,b,c,d) GC_printf(f, (long)a, (long)b, (long)c, \
  1020.                         (long)d, 0l, 0l)
  1021. # define GC_printf5(f,a,b,c,d,e) GC_printf(f, (long)a, (long)b, (long)c, \
  1022.                           (long)d, (long)e, 0l)
  1023. # define GC_printf6(f,a,b,c,d,e,g) GC_printf(f, (long)a, (long)b, (long)c, \
  1024.                         (long)d, (long)e, (long)g)
  1025.  
  1026. void GC_err_printf(/* format, a, b, c, d, e, f */);
  1027. # define GC_err_printf0(f) GC_err_puts(f)
  1028. # define GC_err_printf1(f,a) GC_err_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l)
  1029. # define GC_err_printf2(f,a,b) GC_err_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l)
  1030. # define GC_err_printf3(f,a,b,c) GC_err_printf(f, (long)a, (long)b, (long)c, \
  1031.                           0l, 0l, 0l)
  1032. # define GC_err_printf4(f,a,b,c,d) GC_err_printf(f, (long)a, (long)b, \
  1033.                             (long)c, (long)d, 0l, 0l)
  1034. # define GC_err_printf5(f,a,b,c,d,e) GC_err_printf(f, (long)a, (long)b, \
  1035.                               (long)c, (long)d, \
  1036.                               (long)e, 0l)
  1037. # define GC_err_printf6(f,a,b,c,d,e,g) GC_err_printf(f, (long)a, (long)b, \
  1038.                             (long)c, (long)d, \
  1039.                             (long)e, (long)g)
  1040.             /* Ditto, writes to stderr.            */
  1041.             
  1042. void GC_err_puts(/* char *s */);
  1043.             /* Write s to stderr, don't buffer, don't add    */
  1044.             /* newlines, don't ...                */
  1045.  
  1046. # endif /* GC_PRIVATE_H */
  1047.